package com.yuesystem.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yuesystem.common.BaseContext;
import com.yuesystem.common.CustomException;
import com.yuesystem.common.R;
import com.yuesystem.config.SmsConfig;
import com.yuesystem.dto.requestbody.ForgetPasswordRequestBody;
import com.yuesystem.dto.requestbody.RegisterRequestBody;
import com.yuesystem.dto.requestbody.ResetPasswordRequestBody;
import com.yuesystem.dto.responsebody.UserResponseBody;
import com.yuesystem.entity.SmsLog;
import com.yuesystem.entity.User;
import com.yuesystem.service.ApplyService;
import com.yuesystem.service.BlogService;
import com.yuesystem.service.MsmService;
import com.yuesystem.service.SmsLogService;
import com.yuesystem.service.UserService;
import com.yuesystem.util.JwtUtil;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;


/**
 * 用户控制类.
 */
@RestController
@RequestMapping("/users")
@CrossOrigin
@Slf4j
@Transactional
public class UserController {
  @Autowired
  private UserService userService;
  
  @Autowired
  private MsmService msmService;
  
  @Autowired
  private SmsConfig smsConfig;
  
  @Autowired
  private BlogService blogService;
  
  @Autowired
  private ApplyService applyService;
  
  @Autowired
  private SmsLogService smsLogService;
  
  /**
   * 用户登录.
   *
   * @param map 输入信息
   * @param response 网页信息
   * @return 用户返回体
   */
  @PostMapping("/login")
  public R<UserResponseBody> login(@RequestBody Map map, HttpServletResponse response) {
    String password = map.get("password").toString();
    User one = userService.loginCheck(map.get("phone").toString(), password);
    
    if (one == null) {
      return R.error("账号或密码错误，请重试");
    }
    Map<String, String> payload = new HashMap<>();
    // 加入一些非敏感的用户信息
    payload.put("userId", one.getId().toString());
    // 加入一些非敏感的用户信息
    payload.put("userName", one.getUserName());
    // 用户身份信息
    payload.put("status", String.valueOf(one.getStatus()));
    String jwt = JwtUtil.generateToken(payload);
    response.addHeader("Authorization", jwt);
    
    log.info("user已成功登录: {}", one);
    LocalDateTime createTime = one.getCreateTime();
    log.info("用户创建时间是：{}", createTime);
    
    UserResponseBody userResponseBody = new UserResponseBody();
    userResponseBody.setId(one.getId());
    userResponseBody.setUserName(one.getUserName());
    userResponseBody.setPhone(one.getPhone());
    userResponseBody.setImg(one.getImg());
    userResponseBody.setStatus(one.getStatus());
    userResponseBody.setToken(jwt);
    
    return R.success(userResponseBody);
  }
  
  /**
   * 退出登录.
   *
   * @return 登出信息
   */
  @PostMapping("/logout")
  public R<String> logout() {
    return R.success("退出成功，欢迎下次再来！");
  }
  
  
  /**
   * 发送短信验证码.
   *
   * @param phone 手机号
   * @return 发送操作反馈
   */
  @GetMapping("/send")
  public R<String> sendCode(@RequestParam("phone") String phone) {
    // 生成随机验证码
    String random = smsConfig.printRandom();
    log.info(random);
    boolean sendSuccess = msmService.send(phone, random);
    if (sendSuccess) {
      //将验证码保存到数据库
      SmsLog smsLog = new SmsLog();
      smsLog.setPhone(phone);
      smsLog.setCode(random);
      smsLogService.save(smsLog);
      
      return R.success(random);
    } else {
      // 发送失败
      return R.error("发送短信失败");
    }
  }
  
  
  /**
   * 用户注册账号,注册后跳转到登录界面.
   *
   * @return 注册操作反馈
   */
  @PostMapping("/register")
  public R<String> register(@RequestBody RegisterRequestBody registerRequestBody) {
    String phone = registerRequestBody.getPhone();
    String code = registerRequestBody.getCode();
    String password = registerRequestBody.getPassword();
    String confirmPassword = registerRequestBody.getConfirmPassword();
    userService.register(phone, code, password, confirmPassword);
    return R.success("注册成功，请登录后进入系统");
  }
  
  
  /**
   * 根据id查询个人信息.
   *
   * @return 获取用户信息
   */
  @GetMapping("/userMassage")
  public R<User> getUserMassageById() {
    // 得到个人ID
    Long userId = BaseContext.getCurrentId();
    
    // 调用service层方法
    User one = userService.getUserMassageById(userId);
    return R.success(one);
  }
  
  
  /**
   * 修改个人基本信息.
   *
   * @param user 用户
   * @return 修改个人信息操作反馈
   */
  @PutMapping("changeMassage")
  public R<String> update(@RequestBody User user) {
    log.info("hello");
    log.info(user.toString());
    userService.updateMassageById(user);
    return R.success("修改个人信息成功");
  }
  
  /**
   * 忘记密码.
   *
   * @param forgetPasswordRequestBody 用户输入信息
   * @return 修改密码操作反馈
   */
  @PutMapping("/forget")
  public R<String> forgetPassword(@RequestBody ForgetPasswordRequestBody forgetPasswordRequestBody
  ) {
    String phone = forgetPasswordRequestBody.getPhone();
    String code = forgetPasswordRequestBody.getCode();
    String newPassword = forgetPasswordRequestBody.getNewPassword();
    String newConfirmPassword = forgetPasswordRequestBody.getNewConfirmPassword();
    userService.forgetPassword(phone, code, newPassword, newConfirmPassword);
    return R.success("重置密码成功！请登录进入系统");
  }
  
  /**
   * 重置密码.
   *
   * @param resetPasswordRequestBody 输入信息
   * @return 修改密码操作反馈
   */
  @PutMapping("/reset")
  public R<String> resetPassword(@RequestBody ResetPasswordRequestBody resetPasswordRequestBody) {
    String oldPassword = resetPasswordRequestBody.getOldPassword();
    String newPassword = resetPasswordRequestBody.getNewPassword();
    String confirmNewPassword = resetPasswordRequestBody.getConfirmNewPassword();
    userService.resetPassword(oldPassword, newPassword, confirmNewPassword);
    return R.success("密码修改成功！");
  }
  
  
  /**
   * 分页显示用户.
   *
   * @param page 页面个数
   * @param pageSize 页面大小
   * @param name 用户
   * @param phone 用户号码
   * @return 用户表
   */
  @GetMapping("/getUsers")
  public R<Page<User>> getUsers(@RequestParam int page, @RequestParam int pageSize,
                                @RequestParam String name, @RequestParam String phone) {
    int status = 0;
    Page<User> pageInfo = userService.getUsers(page, pageSize, name, phone, status);
    return R.success(pageInfo);
  }
  
  /**
   * 分页显示编辑信息.
   *
   * @param page 页面个数
   * @param pageSize 页面大小
   * @param name 编辑
   * @param phone 电话号码
   * @return 编辑表
   */
  @GetMapping("/getEdits")
  public R<Page<User>> getEdit(@RequestParam int page, @RequestParam int pageSize,
                               @RequestParam String name, @RequestParam String phone) {
    int status = 1;
    Page<User> pageInfo = userService.getUsers(page, pageSize, name, phone, status);
    return R.success(pageInfo);
  }
  
  /**
   * 获取客服信息.
   *
   * @param page 页面个数
   * @param pageSize 页面大小
   * @param name 编辑
   * @param phone 电话号码
   * @return 客服表
   */
  @GetMapping("/getServs")
  public R<Page<User>> getServ(@RequestParam int page, @RequestParam int pageSize,
                               @RequestParam String name, @RequestParam String phone) {
    int status = 3;
    Page<User> pageInfo = userService.getUsers(page, pageSize, name, phone, status);
    return R.success(pageInfo);
  }
  
  /**
   * 升级用户为编辑.
   *
   * @param id 用户id
   * @return 升级为编辑操作反馈
   */
  @PutMapping("/upgrade1/{id}")
  public R<String> upgrade1(@PathVariable Long id) {
    int status = BaseContext.getCurrentUser().getStatus();
    if (status != 2) {
      throw new CustomException("您未获得该权限！");
    }
    
    userService.upgrade1(id);
    return R.success("升级成功！");
  }
  
  /**
   * 升级为管理员.
   *
   * @param id 用户id
   * @return 升级为管理员操作反馈
   */
  @PutMapping("/upgrade2/{id}")
  public R<String> upgrade2(@PathVariable Long id) {
    int status = BaseContext.getCurrentUser().getStatus();
    if (status != 2) {
      throw new CustomException("您未获得该权限！");
    }
    userService.upgrade2(id);
    return R.success("升级成功！");
  }
  
  
  /**
   * 用户自己注销账.
   *
   * @return 注销操作反馈
   */
  @DeleteMapping("/cancel")
  @Transactional
  public R<String> userCancel(HttpServletRequest request) {
    Long userId = BaseContext.getCurrentId();
    // 1.更改user表的isDeleted字段为1
    User one = userService.getById(userId);
    one.setIsDeleted(1);
    userService.updateById(one);
    
    // 2.删除申请表中申请未处理的条目
    applyService.deleteById(userId);

    // 清理session中用户保存的ID
    request.getSession().removeAttribute("user");
    
    return R.success("注销成功");
  }
  
  /**
   * 管理员注销账号.
   *
   * @return 注销操作反馈
   */
  @DeleteMapping("/cancel/{userId}")
  @Transactional
  public R<String> adminCancel(@PathVariable Long userId, HttpServletRequest request) {
    int status = BaseContext.getCurrentUser().getStatus();
    if (status != 2) {
      throw new CustomException("您未获得该权限！");
    }
    
    // 1.更改user表的isDeleted字段为1
    User one = userService.getById(userId);
    one.setIsDeleted(1);
    userService.updateById(one);
    
    // 2.删除申请表中申请未处理的条目
    applyService.deleteById(userId);
    
    return R.success("注销成功");
  }

  /**
   * 管理员注销账号.
   *
   * @return 注销操作反馈
   */
  @DeleteMapping("/cancelIdentity/{userId}")
  @Transactional
  public R<String> adminCancelIdentity(@PathVariable Long userId, HttpServletRequest request) {
    int status = BaseContext.getCurrentUser().getStatus();
    if (status != 2) {
      throw new CustomException("您未获得该权限！");
    }

    // 1.更改user表的status字段为0(用户)
    User one = userService.getById(userId);
    one.setStatus(0);
    userService.updateById(one);

    return R.success("注销成功");
  }
  
  /**
   * 判断令牌.
   *
   * @return 令牌判断结果
   */
  @GetMapping("/judgeToken")
  public R<String> judgeToken() {
    return R.success("令牌正常");
  }
}
